package com.jy.rhin.support.polymorphism.convertor;

import cn.org.chiss.rhin._2015.base.document.Association;
import cn.org.chiss.rhin._2015.base.document.DocumentEntry;
import cn.org.chiss.rhin._2015.base.document.Folder;
import cn.org.chiss.rhin._2015.base.document.SubmissionSet;
import cn.org.chiss.rhin._2015.base.object.RegObject;
import cn.org.chiss.rhin._2015.base.object.Slot;
import cn.org.chiss.rhin._2015.document.management.DocumentStoredQueryResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jy.rhin.infra.exception.RhinAggrErrorType;
import com.jy.rhin.infra.repo.document.submission.query.DocumentSubmissionQueryHandler;
import com.jy.rhin.sdk.dto.document.DocumentAssociationDto;
import com.jy.rhin.sdk.dto.document.DocumentEntryDto;
import com.jy.rhin.sdk.dto.document.DocumentFolderDto;
import com.jy.rhin.sdk.dto.document.DocumentResultDto;
import com.jy.rhin.support.util.Asserts;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author dhl
 * @date 2022/6/22
 * @Description
 */
public abstract class AbstractDocumentQueryHandler<Req, Resp> implements DocumentQueryHandler {
    @Resource
    DocumentSubmissionQueryHandler documentSubmissionQueryHandler;

    @Override
    public DocumentStoredQueryResponse documentStoredQuery(List<Slot> slotList) {
        //将xml自定义的String类转为java.lang.String的键值对
        Map<String, List<String>> dtoValueMap = slotList.stream().collect(Collectors.toMap(this::getKey, this::getValue));
        //各实例封装键值对返回reqDTO
        Req req = convertReq(dtoValueMap);
        //调用各实例自己的方法拿到基础服务的返回值
        DocumentResultDto<Resp> result = query(req);
        Asserts.isFalse(ObjectUtils.isEmpty(result) || CollectionUtils.isEmpty(result.getResultObject()) || CollectionUtils.isEmpty(result.getJsonTextList()), RhinAggrErrorType.RESPONSE_EMPTY_ERROR);

        //结果值转换后 各实例根据需要自行封装返回对象
        List<Resp> resultList = result.getResultObject();
        List<String> jsonTextList = result.getJsonTextList();
        return convertResp(resultList, jsonTextList);
    }

    /**
     * 查询dto获取
     *
     * @param dtoValueMap xml入参键值对
     * @return
     */
    abstract Req convertReq(Map<String, List<String>> dtoValueMap);

    /**
     * 查询
     *
     * @param req
     * @return
     */
    abstract DocumentResultDto<Resp> query(Req req);

    /**
     * 查询结果匹配返回
     *
     * @param resultList
     * @param jsonTextList
     * @return
     */
    abstract DocumentStoredQueryResponse convertResp(List<Resp> resultList, List<String> jsonTextList);

    /**
     * 获取xml slot的key
     *
     * @param slot
     * @return
     */
    private String getKey(Slot slot) {
        return slot.getName().getValue();
    }

    /**
     * 获取xml slot的value
     *
     * @param slot
     * @return
     */
    private List<String> getValue(Slot slot) {
        return slot.getValueList().getValue().stream().map(cn.org.chiss.rhin._2015.base.String::getValue).collect(Collectors.toList());
    }

    /**
     * 文件夹数据匹配转换
     *
     * @param resultList
     * @param jsonTextList
     * @return
     */
    protected DocumentStoredQueryResponse folderConvert(List<DocumentFolderDto> resultList, List<String> jsonTextList) {

        List<Folder> respList = new ArrayList<>();
        List<String> entryUniqueIdList = resultList.stream().map(DocumentFolderDto::getUniqueId).collect(Collectors.toList());
        for (String str : jsonTextList) {
            JSONObject jsonObject = JSON.parseObject(str);
            if (jsonObject == null) {
                continue;
            }
            List<Folder> folderList = JSON.parseArray(jsonObject.getString("folderList"), Folder.class);
            if (folderList == null) {
                continue;
            }
            for (Folder folder : folderList) {
                if (folder.getUniqueId() == null) {
                    continue;
                }
                if (folder.getUniqueId().getValue() != null && entryUniqueIdList.contains(folder.getUniqueId().getValue())) {
                    respList.add(folder);
                }
            }
        }

        DocumentStoredQueryResponse response = new DocumentStoredQueryResponse();
        response.setFolder(respList);
        return response;
    }

    /**
     * 文档数据匹配转换
     *
     * @param resultList
     * @param jsonTextList
     * @return
     */
    protected DocumentStoredQueryResponse entryConvert(List<DocumentEntryDto> resultList, List<String> jsonTextList) {
        List<DocumentEntry> respList = new ArrayList<>();
        List<String> entryUniqueIdList = resultList.stream().map(DocumentEntryDto::getUniqueId).collect(Collectors.toList());
        for (String str : jsonTextList) {
            JSONObject jsonObject = JSON.parseObject(str);
            List<DocumentEntry> entryList = JSON.parseArray(jsonObject.getString("documentEntryList"), DocumentEntry.class);
            if (!ObjectUtils.isEmpty(entryList)) {
                for (DocumentEntry folder : entryList) {
                    if (entryUniqueIdList.contains(folder.getUniqueId().getValue())) {
                        respList.add(folder);
                    }
                }
            }
        }
        DocumentStoredQueryResponse response = new DocumentStoredQueryResponse();
        response.setDocumentEntry(respList);
        return response;
    }

    /**
     * 文档关联数据匹配转换
     *
     * @param resultList
     * @param jsonTextList
     * @return
     */
    protected DocumentStoredQueryResponse associationConvert(List<DocumentAssociationDto> resultList, List<String> jsonTextList) {
        List<Association> respList = new ArrayList<>();
        List<String> entryUniqueIdList = resultList.stream().map(DocumentAssociationDto::getTargetId).collect(Collectors.toList());
        for (String str : jsonTextList) {
            JSONObject jsonObject = JSON.parseObject(str);
            List<Association> associationList = JSON.parseArray(jsonObject.getString("associationList"), Association.class);
            for (Association association : associationList) {
                if (entryUniqueIdList.contains(association.getTargetObject().getId().getValue())) {
                    respList.add(association);
                }
            }
        }

        DocumentStoredQueryResponse response = new DocumentStoredQueryResponse();
        response.setAssociation(respList);
        return response;
    }

    /**
     * 提交集数据匹配转换
     *
     * @param jsonTextList
     * @return
     */
    protected DocumentStoredQueryResponse submissionSetConvert(List<String> jsonTextList) {
        DocumentStoredQueryResponse response = new DocumentStoredQueryResponse();
        List<SubmissionSet> submissionSetList = new ArrayList<>();
        for (String str : jsonTextList) {
            List<RegObject> regObjectList = new ArrayList<>();
            JSONObject jsonObject = JSON.parseObject(str);
            List<Association> associationList = JSON.parseArray(jsonObject.getString("associationList"), Association.class);
            List<DocumentEntry> entryList = JSON.parseArray(jsonObject.getString("documentEntryList"), DocumentEntry.class);
            List<Folder> folderList = JSON.parseArray(jsonObject.getString("folderList"), Folder.class);
            if (!ObjectUtils.isEmpty(associationList)) {
                regObjectList.addAll(associationList);
            }
            if (!ObjectUtils.isEmpty(entryList)) {
                regObjectList.addAll(entryList);
            }
            if (!ObjectUtils.isEmpty(folderList)) {
                regObjectList.addAll(folderList);
            }
            SubmissionSet submissionSet = JSON.parseObject(str, SubmissionSet.class);
            submissionSet.setFolderOrDocumentEntryOrAssociation(regObjectList);
            submissionSetList.add(submissionSet);
        }
        response.setSubmissionSet(submissionSetList);
        return response;
    }
}